package com.plat.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.activiti.engine.HistoryService;
import org.activiti.engine.IdentityService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricProcessInstanceQuery;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.runtime.ProcessInstanceQuery;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.plat.dao.IBaseDao;
import com.plat.security.dao.LeaveDao;
import com.plat.security.entity.Leave;
import com.plat.service.ILeave;
import com.plat.tag.core.json.DataGrid;

@Service
@Transactional
public class LeaveServiceImpl extends BaseServiceImpl<Leave> implements ILeave {

	@Autowired
	private LeaveDao dao;

	@Autowired
	private RuntimeService runtimeService;

	@Autowired
	protected TaskService taskService;

	@Autowired
	protected HistoryService historyService;

	@Autowired
	protected RepositoryService repositoryService;

	@Autowired
	private IdentityService identityService;

	@Override
	public IBaseDao<Leave> getDao() {
		return dao;
	}

	@Override
	public ProcessInstance saveWorkflow(Leave entity, Map<String, Object> variables) {

		getDao().save(entity);

		String businessKey = entity.getId().toString();

		identityService.setAuthenticatedUserId(entity.getUserId());

		ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("leave", businessKey, variables);
		String processInstanceId = processInstance.getId();
		entity.setProcessInstanceId(processInstanceId);
		return processInstance;
	}

	@Override
	@Transactional(readOnly = true)
	public List<Leave> findTodoTasks(String userId, DataGrid dataGrid, List<String> groups) {
		List<Leave> results = new ArrayList<Leave>();
		List<Task> tasks = new ArrayList<Task>();

		// 根据当前人的ID查询
		// TaskQuery taskQuery =
		// taskService.createTaskQuery().processDefinitionKey("leave").taskAssignee(userId).active()
		// .orderByTaskId().desc().orderByTaskCreateTime().desc();

		TaskQuery taskQuery = taskService.createTaskQuery().processDefinitionKey("leave").taskCandidateGroupIn(groups)
				.active().orderByTaskId().desc().orderByTaskCreateTime().desc();

		List<Task> todoList = taskQuery.list();

		// 根据当前人未签收的任务
		TaskQuery claimQuery = taskService.createTaskQuery().processDefinitionKey("leave").taskAssignee(userId)
				.active().orderByTaskId().desc().orderByTaskCreateTime().desc();
		List<Task> unsignedTasks = claimQuery.list();

		tasks.addAll(todoList);
		tasks.addAll(unsignedTasks);

		for (Task task : tasks) {
			String processInstanceId = task.getProcessInstanceId();
			ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
					.processInstanceId(processInstanceId).active().singleResult();
			String businessKey = processInstance.getBusinessKey();
			if (businessKey == null) {
				continue;
			}
			Leave leave = dao.get(Long.parseLong(businessKey));

			if (leave == null) {
				continue;
			}
			leave.setProcessInstance(processInstance);
			leave.setProcessDefinition(getProcessDefinition(processInstance.getProcessDefinitionId()));
			// leave.setTask(task);
			leave.setTaskId(task.getId());
			leave.setTaskName(task.getName());
			leave.setAssignee(task.getAssignee());
			leave.setTaskDefinitionKey(task.getTaskDefinitionKey());
			results.add(leave);
		}
		return results;
	}

	/**
	 * 查询流程定义对象
	 * 
	 * @param processDefinitionId 流程定义ID
	 * @return
	 */
	protected ProcessDefinition getProcessDefinition(String processDefinitionId) {
		ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
				.processDefinitionId(processDefinitionId).singleResult();
		return processDefinition;
	}

	@Transactional(readOnly = true)
	public List<Leave> findRunningProcessInstaces(DataGrid dataGrid, List<String> groups) {
		List<Leave> results = new ArrayList<Leave>();
		ProcessInstanceQuery query = runtimeService.createProcessInstanceQuery().processDefinitionKey("leave").active()
				.orderByProcessInstanceId().desc();
		List<ProcessInstance> list = query.list();

		// 关联业务实体
		for (ProcessInstance processInstance : list) {
			String businessKey = processInstance.getBusinessKey();
			if (businessKey == null) {
				continue;
			}
			Leave leave = dao.get(Long.parseLong(businessKey));

			if (leave == null) {
				continue;
			}
			leave.setProcessInstance(processInstance);
			leave.setProcessDefinition(getProcessDefinition(processInstance.getProcessDefinitionId()));
			results.add(leave);

			// 设置当前任务信息
			List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstance.getId()).active()
					.orderByTaskCreateTime().desc().listPage(0, 1);

			Task runTask = tasks.get(0);
			leave.setTask(runTask);
			leave.setTaskId(runTask.getId());
			leave.setTaskName(runTask.getName());
			leave.setAssignee(runTask.getAssignee());
			leave.setTaskDefinitionKey(runTask.getTaskDefinitionKey());
			leave.setAssignee(runTask.getAssignee());
		}
		return results;
	}

	/**
	 * 读取已结束中的流程
	 * 
	 * @return
	 */
	@Transactional(readOnly = true)
	public List<Leave> findFinishedProcessInstaces() {
		List<Leave> results = new ArrayList<Leave>();
		HistoricProcessInstanceQuery query = historyService.createHistoricProcessInstanceQuery()
				.processDefinitionKey("leave").finished().orderByProcessInstanceEndTime().desc();
		List<HistoricProcessInstance> list = query.list();

		// 关联业务实体
		for (HistoricProcessInstance historicProcessInstance : list) {
			String businessKey = historicProcessInstance.getBusinessKey();
			Leave leave = dao.get(new Long(businessKey));

			if (leave == null) {
				continue;
			}

			leave.setProcessDefinition(getProcessDefinition(historicProcessInstance.getProcessDefinitionId()));
			leave.setHistoricProcessInstance(historicProcessInstance);
			results.add(leave);
		}
		return results;
	}
}
